package sample.algo.sistr.algosample.algos.avl;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

import java.util.Deque;

public class TreeView extends View {

    private static Paint nodeOutline;
    private static Paint nodeText;

    private float canvasWidth;
    private float canvasHeight;

    private float nodeWidth;
    private float nodeHeight;

    static {
        nodeOutline = new Paint();
        nodeOutline.setColor(Color.BLACK);
        nodeOutline.setStyle(Paint.Style.STROKE);
        nodeOutline.setStrokeWidth(5.0f);

        nodeText = new Paint();
        nodeText.setColor(Color.BLACK);
        nodeText.setStyle(Paint.Style.FILL);
        nodeText.setStrokeWidth(3.0f);
        nodeText.setTextSize(40.0f);
    }

    Node<Integer> root;

    public TreeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        root = null;
        canvasWidth = 1;
        canvasHeight = 1;
    }

    public void SetTree(Node<Integer> root) {
        this.root = root;
        this.invalidate();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvasWidth = canvas.getWidth();
        canvasHeight = canvas.getHeight();

        nodeWidth = canvasWidth*0.1f;
        nodeHeight = canvasWidth*0.1f;

        drawTree(root, canvas, Math.max(root.leftHeight, root.rightHeight), Math.max(root.leftHeight, root.rightHeight), canvasWidth/2.0f, nodeHeight);
    }

    private void drawTree(Node<Integer> node, Canvas canvas, int treeHeight, int currentHeight, float X, float Y) {

        // Draw node external square
        canvas.drawRect(X-nodeWidth/2.0f, Y-nodeHeight/2.0f, X+nodeWidth/2.0f, Y+nodeHeight/2.0f, nodeOutline);

        // Write node value inside the square
        String strVal = node.val.toString();
        Rect bounds = new Rect();
        nodeText.getTextBounds(strVal, 0, strVal.length(), bounds);
        nodeText.setColor(Color.BLACK);
        canvas.drawText(strVal, X - bounds.width()/2.0f, Y+ bounds.height()/2.0f, nodeText);

        // Write node left height
        strVal = Integer.toString(node.leftHeight);
        nodeText.setColor(Color.RED);
        canvas.drawText(strVal, X - nodeWidth/2.0f + nodeWidth*0.05f, Y+ nodeHeight/2.0f - nodeHeight*0.05f, nodeText);

        // Write node right height
        strVal = Integer.toString(node.rightHeight);
        nodeText.getTextBounds(strVal, 0, strVal.length(), bounds);
        canvas.drawText(strVal, X + nodeWidth/2.0f - bounds.width() - nodeWidth*0.05f, Y+ nodeHeight/2.0f - nodeHeight*0.05f, nodeText);

        if(node.l != null || node.r != null) {
            // number of node on the child line
            int nbNodeChildLine = int_pow(2, treeHeight-currentHeight+1);
            int nbNodeLastLine = int_pow(2, treeHeight);

            float space = ((nbNodeLastLine-nbNodeChildLine)*nodeWidth)/(nbNodeChildLine*2.0f) + nodeWidth/2.0f;

            if (node.l != null) {
                drawTree(node.l, canvas, treeHeight, --currentHeight, X-space, Y + nodeHeight*1.4f);
            }
            if (node.r != null) {
                drawTree(node.r, canvas, treeHeight, currentHeight, X+space, Y + nodeHeight*1.4f);
            }

        }
    }

    private int int_pow(int base, int exp)
    {
        int result = 1;
        while (exp > 0)
        {
            result *= base;
            exp --;
        }

        return result;
    }
}
